package com.arrayofsky.gateway.server;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import lombok.extern.slf4j.Slf4j;

import java.net.InetSocketAddress;
import java.util.concurrent.Callable;

/**
 * @Author: gaoyifeng
 * @Description: 会话服务器
 * @Date Created in 2024-06-18-11:32
 * @Modified By:
 */
@Slf4j
public class SessionServer  implements Callable<Channel> {

    /**
     * 线程组
     * EventLoopGroup：EventLoopGroup是Netty中处理I/O操作的线程池。
     * 它包含了一个或多个EventLoop，每个EventLoop负责处理一个或多个Channel的I/O事件。
     *
     * boss和work：这两个EventLoopGroup是用于处理不同类型的任务。
     * boss用于接收连接并将其注册到work中进行处理。
     */
    private final EventLoopGroup boss = new NioEventLoopGroup(1);
    private final EventLoopGroup work = new NioEventLoopGroup();


    /**
     * 绑定的channel
     * Channel是Netty中的抽象概念，代表了一个网络连接。通过Channel可以进行数据的读写操作。
     */
    private Channel channel;

    @Override
    public Channel call() throws Exception {

        // ChannelFuture是Netty中表示异步操作结果的对象。它代表一个尚未完成的I/O操作，例如连接的建立、数据的发送或接收等。
        // 通过ChannelFuture，可以获取操作的状态、添加监听器以便在操作完成时执行相应的逻辑，或者等待操作完成。
        // ChannelFuture提供了以下常用方法：
        // - addListener(GenericFutureListener<? extends Future<? super Void>> listener)：
        //  - 向ChannelFuture添加一个监听器，在操作完成时执行相应的逻辑。
        //  - 监听器可以是一个回调函数或者一个ChannelFutureListener实例。
        // - sync()：阻塞当前线程，直到操作完成。如果操作失败，会抛出相应的异常。
        // - await()：阻塞当前线程，直到操作完成。如果操作失败，不会抛出异常，而是返回一个表示操作失败的ChannelFuture。
        // - isDone()：判断操作是否已经完成。
        // - isSuccess()：判断操作是否成功完成。
        // - cause()：获取操作失败的原因。
        // ChannelFuture被用于等待服务器绑定操作的完成。
        // 通过调用syncUninterruptibly()方法，当前线程会一直阻塞，直到服务器绑定完成或发生异常。
        // 在finally块中，使用channelFuture.isSuccess()判断服务器绑定是否成功，以执行相应的日志记录逻辑。
        ChannelFuture channelFuture = null;

        try {

            // ServerBootstrap是Netty用于创建服务器的启动类。它简化了服务器的配置和启动过程。
            ServerBootstrap b = new ServerBootstrap();
            b.group(boss, work)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childHandler(new SessionChannelInitializer());

            channelFuture = b.bind(new InetSocketAddress(7397)).syncUninterruptibly();
            this.channel = channelFuture.channel();

        } catch (Exception e) {
            log.error("socket server start error.", e);
        } finally {
            if (null != channelFuture && channelFuture.isSuccess()) {
                log.info("socket server start done.");
            } else {
                log.error("socket server start error.");
            }
        }
        return channel;
    }



}
